package com.zhglxt.framework.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.io.Serializable;

/**
 * @ClassName RedisConfig
 * @Description Redis配置类
 * @Author moyongjun
 * @Date 2022/6/1 09:39
 * @Version 1.0
 **/
@EnableCaching
@Configuration
//在加载配置的类之后再加载当前类
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class RedisConfig {


    /**
     * 配置redisTemplate针对不同key和value场景下不同序列化的方式,默认的RedisTemplate<String, Object>则失效，此配置起作用
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {

        RedisTemplate<String ,Object> redisTemplate=new RedisTemplate<>();
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
        ObjectMapper om = new ObjectMapper();
        //全局解决反序列化问题：出现这种问题的情况是由于JSON里面包含了实体没有的字段导致反序列化失败。
        om.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
        // 属性可访问性
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);
        redisTemplate.setConnectionFactory(redisConnectionFactory);



//        redisTemplate.setStringSerializer(stringRedisSerializer);

// 设置键（key）的序列化采用StringRedisSerializer。
        redisTemplate.setKeySerializer(stringRedisSerializer);
        // 设置值（value）的序列化采用Jackson2JsonRedisSerializer。
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);

        redisTemplate.setHashKeySerializer(stringRedisSerializer);

        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
//        redisTemplate.setHashValueSerializer(stringRedisSerializer);

        redisTemplate.afterPropertiesSet();
        return  redisTemplate;
    }

    /**
     * redis string操作
     * @param redisTemplate
     * @return
     */
    @Bean
    public ValueOperations valueOperations(RedisTemplate<String,Object> redisTemplate){
        ValueOperations<String, Object> valueOperations = redisTemplate.opsForValue();
        return valueOperations;
    }

    /**
     * redis hash操作
     * @param redisTemplate
     * @return
     */
    @Bean
    public HashOperations hashOperations(RedisTemplate<String,Object> redisTemplate){
        HashOperations<String, Serializable, Object> hashOperations = redisTemplate.opsForHash();
        return hashOperations;
    }

    /**
     * redis list操作
     * @param redisTemplate
     * @return
     */
    @Bean
    public ListOperations listOperations(RedisTemplate<String,Object> redisTemplate){
        ListOperations<String, Object> listOperations = redisTemplate.opsForList();
        return listOperations;
    }

    /**
     * Redis set操作
     * @param redisTemplate
     * @return
     */
    @Bean
    public SetOperations SetOperations(RedisTemplate<String,Object> redisTemplate){
        SetOperations<String, Object> setOperations = redisTemplate.opsForSet();
        return setOperations;
    }

    /**
     * Redis zset操作
     * @param redisTemplate
     * @return
     */
    @Bean
    public ZSetOperations zSetOperations(RedisTemplate<String,Object> redisTemplate){
        ZSetOperations<String, Object> zSetOperations = redisTemplate.opsForZSet();
        return zSetOperations;
    }

    /**
     * redis stream操作
     * @param redisTemplate
     * @return
     */
    @Bean
    public StreamOperations streamOperations(RedisTemplate<String,Object> redisTemplate){
        StreamOperations<String, Object, Object> streamOperations = redisTemplate.opsForStream();
        return streamOperations;
    }




}
